package com.minsf.springbootinit.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.Gson;
import com.minsf.springbootinit.common.ErrorCode;
import com.minsf.springbootinit.constant.CommonConstant;
import com.minsf.springbootinit.exception.ThrowUtils;
import com.minsf.springbootinit.judge.JudgeService;
import com.minsf.springbootinit.mapper.QuestionSubmitMapper;
import com.minsf.springbootinit.judge.codesandbox.model.JudgeInfo;
import com.minsf.springbootinit.model.dto.questionSubmit.QuestionSubmitAddRequest;
import com.minsf.springbootinit.model.dto.questionSubmit.QuestionSubmitQueryRequest;
import com.minsf.springbootinit.model.entity.PostThumb;
import com.minsf.springbootinit.model.entity.Question;
import com.minsf.springbootinit.model.entity.QuestionSubmit;
import com.minsf.springbootinit.model.entity.User;
import com.minsf.springbootinit.model.enums.QuestionLanguageEnum;
import com.minsf.springbootinit.model.enums.QuestionSubmitStatusEnum;
import com.minsf.springbootinit.model.vo.QuestionSubmitVo;
import com.minsf.springbootinit.model.vo.UserVO;
import com.minsf.springbootinit.service.QuestionService;
import com.minsf.springbootinit.service.QuestionSubmitService;
import com.minsf.springbootinit.service.UserService;
import com.minsf.springbootinit.utils.SqlUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * @author a
 * @description 针对表【question_submit(题目提交)】的数据库操作Service实现
 * @createDate 2024-01-03 09:35:32
 */
@Service
public class QuestionSubmitServiceImpl extends ServiceImpl<QuestionSubmitMapper, QuestionSubmit>
        implements QuestionSubmitService {

    @Resource
    private QuestionService questionService;

    @Resource
    private UserService userService;

    @Resource
    @Lazy
    private JudgeService judgeService;

    private Gson gson = new Gson();

    @Override
    public Long doQuestionSubmit(QuestionSubmitAddRequest questionSubmitAddRequest, User loginUser) {
        String language = questionSubmitAddRequest.getLanguage();
        String code = questionSubmitAddRequest.getCode();
        JudgeInfo judgeInfo = questionSubmitAddRequest.getJudgeInfo();
        Long questionId = questionSubmitAddRequest.getQuestionId();

        // 判断实体是否存在，根据类别获取实体
        Question question = questionService.getById(questionId);
        ThrowUtils.throwIf(ObjectUtil.isEmpty(question), ErrorCode.NOT_FOUND_ERROR, "题目不存在");

        final int MAX_LENGTH = 2045;
        ThrowUtils.throwIf(StrUtil.isNotBlank(code) && code.length() > MAX_LENGTH, ErrorCode.PARAMS_ERROR, "代码太长");

        ThrowUtils.throwIf(!QuestionLanguageEnum.getValues().contains(language), ErrorCode.NOT_FOUND_ERROR, "语言不存在");

        long userId = loginUser.getId();
        QuestionSubmit questionSubmit = new QuestionSubmit();
        questionSubmit.setLanguage(language);
        questionSubmit.setCode(code);
        if (ObjectUtil.isNotNull(judgeInfo)) {
            questionSubmit.setJudgeInfo(gson.toJson(judgeInfo));
        }
        questionSubmit.setQuestionId(question.getId());
        // 判题中
        questionSubmit.setStatus(QuestionSubmitStatusEnum.UNDETERMINED_QUESTION.getValue());
        questionSubmit.setUserId(userId);

        boolean save = this.save(questionSubmit);
        ThrowUtils.throwIf(!save, ErrorCode.OPERATION_ERROR, "提交失败！");

        Long questionSubmitId = questionSubmit.getId();
//        CompletableFuture.runAsync(() -> {
           judgeService.doJudge(questionSubmitId);
//        });
        return questionSubmitId;
    }


    /**
     * 获取查询包装类
     *
     * @param questionSubmitQueryRequest
     * @return
     */
    @Override
    public QueryWrapper<QuestionSubmit> getQueryWrapper(QuestionSubmitQueryRequest questionSubmitQueryRequest) {
        Long id = questionSubmitQueryRequest.getId();
        String language = questionSubmitQueryRequest.getLanguage();
        Long questionId = questionSubmitQueryRequest.getQuestionId();
        Integer status = questionSubmitQueryRequest.getStatus();
        Long userId = questionSubmitQueryRequest.getUserId();
//        long current = questionSubmitQueryRequest.getCurrent();
//        long pageSize = questionSubmitQueryRequest.getPageSize();
        String sortField = questionSubmitQueryRequest.getSortField();
        String sortOrder = questionSubmitQueryRequest.getSortOrder();

        QueryWrapper<QuestionSubmit> queryWrapper = new QueryWrapper<>();
        if (questionSubmitQueryRequest == null) {
            return queryWrapper;
        }

        queryWrapper.like(StringUtils.isNotBlank(language), "language", language);

        queryWrapper.eq(ObjectUtils.isNotEmpty(id), "id", id);
        queryWrapper.eq(ObjectUtils.isNotEmpty(status), "status", status);
        queryWrapper.eq(ObjectUtils.isNotEmpty(questionId), "questionId", questionId);
        queryWrapper.eq(ObjectUtils.isNotEmpty(userId), "userId", userId);
        queryWrapper.eq("isDelete", false);
        queryWrapper.orderBy(SqlUtils.validSortField(sortField), sortOrder.equals(CommonConstant.SORT_ORDER_ASC),
                sortField);
        return queryWrapper;
    }

    @Override
    public QuestionSubmitVo grtQuestionSubmitVo(QuestionSubmit questionSubmit, HttpServletRequest request) {
        QuestionSubmitVo questionSubmitVo = QuestionSubmitVo.objToVo(questionSubmit);
        long postId = questionSubmitVo.getId();
        // 1. 关联查询用户信息
        Long userId = questionSubmitVo.getUserId();
        User user = null;
        if (userId != null && userId > 0) {
            user = userService.getById(userId);
        }
        UserVO userVO = userService.getUserVO(user);
        questionSubmitVo.setUser(userVO);
        // 2. 已登录，获取用户点赞、收藏状态
        User loginUser = userService.getLoginUserPermitNull(request);
        if (loginUser != null) {
            // 获取点赞
            QueryWrapper<PostThumb> postThumbQueryWrapper = new QueryWrapper<>();
            postThumbQueryWrapper.in("postId", postId);
            postThumbQueryWrapper.eq("userId", loginUser.getId());
        }
        return questionSubmitVo;
    }

    @Override
    public Page<QuestionSubmitVo> getQuestionSubmitVoPage(Page<QuestionSubmit> postPage, HttpServletRequest request) {
        List<QuestionSubmit> postList = postPage.getRecords();
        Page<QuestionSubmitVo> postVOPage = new Page<>(postPage.getCurrent(), postPage.getSize(), postPage.getTotal());
        if (CollectionUtils.isEmpty(postList)) {
            return postVOPage;
        }
        // 1. 关联查询用户信息
        Set<Long> userIdSet = postList.stream().map(QuestionSubmit::getUserId).collect(Collectors.toSet());
        Map<Long, List<User>> userIdUserListMap = userService.listByIds(userIdSet).stream()
                .collect(Collectors.groupingBy(User::getId));
        // 填充信息
        List<QuestionSubmitVo> postVOList = postList.stream().map(QuestionSubmit -> {
            QuestionSubmitVo questionSubmitVo = QuestionSubmitVo.objToVo(QuestionSubmit);
            Long userId = QuestionSubmit.getUserId();
            User user = null;
            if (userIdUserListMap.containsKey(userId)) {
                user = userIdUserListMap.get(userId).get(0);
            }
            questionSubmitVo.setUser(userService.getUserVO(user));

            return questionSubmitVo;
        }).collect(Collectors.toList());
        postVOPage.setRecords(postVOList);
        return postVOPage;
    }
}




